#ifndef __NETBASE_H__
#define __NETBASE_H__

/**
 * @file NetBase.h
 * @author Lost
 * @date 五月 2018
 * @brief 
 * 服务器网络模块
 */
#include "Poll.h"
#include "DataPool.h"

#ifdef _WIN32
#include <hash_map>
using namespace stdext;
#else
#include <ext/hash_map>
using namespace __gnu_cxx;
#endif
#include <queue>

using std::queue;

/*!< 校验值 */
#define CHECK_VALUE 123456789

/*!< 基础报文 */
#define BASE_DATA_SIZE 64

/*!< 最大报文 */
#define MAX_DATA_SIZE 16384 //1024*16

/*!< 尝试发送的最大次数 */
#define TRY_SEND_TIME 3

/*!< 报文头数据大小 */
#define DATA_SIZE 4


/**
 * @brief 状态枚举
 */
enum EnmNetState
{
    /*!< 初始化 */
    ENM_INIT = 0,
    /*!< 连接中 */
    ENM_CONNECTING,
    /*!< 已连接 */
    ENM_CONNECTED,
    /*!< 监听中 */
    ENM_LISTENING,
    /*!< 已监听 */
    ENM_LISTENED,
    /*!< 获取连接中 */
    ENM_ACCEPTTING,
    /*!< 已获取连接 */
    ENM_ACCEPTED,
    /*!< 接收数据中 */
    ENM_RECVING,
    /*!< 已接收数据 */
    ENM_RECVED,
    /*!< 发送数据中 */
    ENM_SENDING,
    /*!< 已发送数据 */
    ENM_SENDED,
};

/**
 * @brief 网络报文头结构
 */
typedef struct stNetPacket
{
    /*!< 长度 */
    int uLength;

    /*!< 标记位 */
    int uFlag;

    /*!< 校验值 */
    int uCheckValue;

    /*!< 数据 */
    char csData[DATA_SIZE];
}SNetPacket;

/**
 * @brief 缓存节点
 */
typedef struct stBufferNode
{
    /*!< 已经发送/接收字节 */
    int iDealed;

    /*!< 总字节 */
    int iTotal;

    /*!< 缓存节点上一节点 */
    struct stBufferNode *pPrev;

    /*!< 缓存节点下一节点 */
    struct stBufferNode *pNext;

    /*!< 缓存节点报文 */
    SNetPacket stNetPacket;

public:
    /**
     * @brief 移除节点
     */
    static struct stBufferNode *RemoveNode(struct stBufferNode *pRemoveNode)
    {
        if (pRemoveNode == NULL)
        {
            return NULL;
        }

        if (pRemoveNode->pNext == pRemoveNode)
        {
            return NULL;
        }

        if (pRemoveNode->pNext == NULL || pRemoveNode->pPrev == NULL)
        {
            printf("ERROR RemoveNode|pRemoveNode->pNext or pRemoveNode->pPrev is NULL\n");
            return NULL;
        }

        struct stBufferNode *pNextNode = pRemoveNode->pNext;
        
        pNextNode->pPrev = pRemoveNode->pPrev;
        pRemoveNode->pPrev->pNext = pNextNode;

        return pNextNode;
    }

    /**
     * @brief 插入节点
     */
    static bool AddNode(struct stBufferNode *&pCurNode, struct stBufferNode *pNewNode)
    {
        if (pNewNode == NULL)
        {
            printf("ERROR AddNode|pNewNode is NULL\n");
            return false;
        }

        if (pCurNode == NULL)
        {
            pCurNode = pNewNode;
            pNewNode->pNext = pNewNode->pPrev = pNewNode;
            
            return true;
        }

        if (pCurNode->pPrev == NULL || pCurNode->pNext == NULL)
        {
            printf("ERROR AddNode|pCurNode->pPrev or pCurNode->pNext is NULL\n");
            return false;
        }

        pCurNode->pPrev->pNext = pNewNode;
        pNewNode->pNext = pCurNode;

        pNewNode->pPrev = pCurNode->pPrev;
        pCurNode->pPrev = pNewNode;


        return true;
    }

    /**
     * @brief 获取前一个节点
     */
    static struct stBufferNode *GetPrevNode(struct stBufferNode *pCurNode) 
    {
        if (pCurNode == NULL)
        {
            printf("ERROR GetPrevNode|pCurNode is NULL\n");
            return NULL;
        }
        return pCurNode->pPrev;
    }

    /**
     * @brief 获取下一个节点
     */
    static struct stBufferNode *GetNextNode(struct stBufferNode *pCurNode)
    {
        if (pCurNode == NULL)
        {
            printf("ERROR GetNextNode|pCurNode is NULL\n");
            return NULL;
        }
        return pCurNode->pNext;
    }
}SBufferNode;

/**
 * @brief 套接字数据
 */
typedef struct stSocketData
{
    /*!< 唯一索引 */
    int iID;

    /*!< 套接字 */
    int iSocket;

    /*!< 状态 */
    EnmNetState eState;

    /*!< 事件类型 @ESocketEventType */
    int iEventType;

    /*!< 即将发送或者接收的数据缓存 */
    char csDataBuffer[MAX_DATA_SIZE];

    /*!< 发送缓存使用大小 */
    int iBufferUse;

    /*!< 发送缓存列表 */
    SBufferNode *pSendHeadNode;

    /*!< 接收缓存列表 */
    SBufferNode *pRecvHeadNode;
}SSocketData;

/**
 * @brief 服务器网络类
 */
class CNetBase
{
public:
    CNetBase();
    ~CNetBase();

public:
    /**
     * @brief 初始化
     */
    virtual bool Init();
    
    /**
     * @brief 添加监听端口
     */
    virtual int AddListen(const char *pIp, int iPort);

    /**
     * @brief 添加连接
     */
    virtual int AddConnect(const char *pIp, int iPort);

    /**
     * @brief 检测网络事件
     */
    virtual int Polling(int iWaitTime);
public:
    /**
     * @brief 收到消息事件
     */
    virtual int OnRecv(const int iSocket, char *pData, int iLen);
    
    /**
     * @brief 接收报文事件
     */
    virtual bool OnPacket(const int iSocket, char *pData, int iLen);

    /**
     * @brief 收到连接事件
     */
    virtual bool OnAccept(const int iListenSocket, const int iClientSocket);

    /**
     * @brief 收到连接事件
     */
    virtual bool OnConnect(const int iSocket);

    /**
     * @brief 收到关闭事件
     */
    virtual bool OnClose(const int iSocket);

    /**
     * @brief 发送报文
     */
    virtual int Send(const int iSocket, const char *pData, const int iLen);

    /**
     * @brief 发送报文
     */
    virtual void Close(const int iSocket);
private:
    /**
     * @brief 创建套接字数据
     */
    SSocketData *CreateSocketData(int iSocket, int iEventType);

    /**
     * @brief 删除套接字数据
     */
    void DeleteSocketData(SSocketData *&pSocketData);

    /**
     * @brief 获取空闲空间
     */
    char *GetFreeData(int iSize);

    /**
     * @brief 释放空间
     */
    void ReleaseData(char * csBuff);

private:
    /*!< 轮询模式 */
    CPoll *m_pPoll;

    /*!< 套接字数据集合 */
    typedef hash_map<int, SSocketData*> SocketMap;
    SocketMap m_mapSocketMap;

    /*!< 基础数据内存池 */
    CDataPool<BASE_DATA_SIZE> m_cBaseDataPool;

    /*!< 4倍基础数据内存池 */
    CDataPool<BASE_DATA_SIZE * 4> m_cBaseDataPool4;

    /*!< 16倍基础数据内存池 */
    CDataPool<BASE_DATA_SIZE * 16> m_cBaseDataPool16;

    /*!< 最大数据内存池 */
    CDataPool<MAX_DATA_SIZE> m_cMaxDataPool;


};


#endif